#include "../base/conf.h"
#include "../server/slave_protocol.h"
#include "../server/msg.h"

#include <stdio.h>
#include <string.h>
#include <assert.h>
#include <malloc.h>

#include "slave_logger_protocol.h"

C_CODE_BEGIN

static const char* _logger_slavename= "Logger";

static int _index_log_level( const char* l ) {
	if( strcmp(l,slave_logger_info_level) == 0 ) {
		return 0;
	} else if( strcmp(l,slave_logger_warn_level)==0 ) {
		return 1;
	} else if( strcmp(l,slave_logger_error_level)==0 ) {
		return 2;
	} else if( strcmp(l,slave_logger_fatal_level)==0 ) {
		return 3;
	} else {
		/* error comes here */
		return -1;
	}
}

/*
 * Main function for this DLL 
 */


EXPORT_FUNC int entry( struct slave_protocol* );


/*
 * Logging context 
 */

struct logger_context {
	/* 4 level logging level */
	FILE* logger_file[4];
};


static int _logger_slave_init( void* ctx ) {
	struct logger_context* lctx = (struct logger_context*)ctx;
	lctx->logger_file[0] = fopen("info.log.txt","w+");
	if( lctx->logger_file[0] == NULL ) {
		return -1;
	}
	lctx->logger_file[1] = fopen("warn.log.txt","w+");
	if( lctx->logger_file[1] == NULL ) {
		return -1;
	}
	lctx->logger_file[2] = fopen("error.log.txt","w+");
	if( lctx->logger_file[2] == NULL ) {
		return -1;
	}
	lctx->logger_file[3] = fopen("fatal.log.txt","w+");
	if( lctx->logger_file[3] == NULL ) {
		return -1;
	}
	return 1;
}


/*
 * Write the content into the specific log file 
 */
static void _record( struct logger_context* ctx, const char* type , const char* src, size_t sid , const char* content ) {
	int logidx = _index_log_level(type);
	fprintf ( ctx->logger_file[logidx] , "[%s::{%s,%d}]:%s\n" , type , src, sid , content );
	if( logidx !=0 ) {
		fflush(ctx->logger_file[logidx]);
	}
}


static void _error( struct logger_context* ctx, const char* type, size_t sid , const char* src ) {
	int logidx = _index_log_level(slave_logger_error_level);
	fprintf( ctx->logger_file[logidx] , "[%s::{%s,%d}]:Can't record!",type,src,sid);
}

/*
 * Logger main callback function which performs the real logic for handling the message
 */
static void _logger_slave_cb( struct message* msg , void* arg , struct slave_api* api ) {
	/* get the message protocol */
	struct slave_logger_protocol* lpro = (struct slave_logger_protocol*)(msg->msg);
	struct logger_context* lctx = (struct logger_context*)(arg);
	int logidx = _index_log_level(lpro->type);
	if( logidx == -1 ) {
		_error(lctx,lpro->type,msg->sid,msg->src);
		return ;
	} 
	/* record the message here */
	_record(lctx,lpro->type,msg->src,msg->sid,lpro->content);
}


static void _logger_slave_clean( void* arg ) {
	struct logger_context* lctx = (struct logger_context*)arg;
	if( lctx->logger_file[0] != NULL )
		fclose(lctx->logger_file[0]);
	if( lctx->logger_file[1] != NULL )
		fclose(lctx->logger_file[1]);
	if( lctx->logger_file[2] != NULL )
		fclose(lctx->logger_file[2]);
	if( lctx->logger_file[3] != NULL )
		fclose(lctx->logger_file[3]);
}

/*
 * Export main function 
 */
EXPORT_FUNC int entry( struct slave_protocol* slpro ) {
	struct logger_context* lctx;
	slpro->argument = malloc(sizeof(struct logger_context));
	lctx = (struct logger_context*)slpro->argument;
	slpro->cb = _logger_slave_cb;
	slpro->init=_logger_slave_init;
	slpro->clean=_logger_slave_clean;
	slpro->slavename = _logger_slavename;
	lctx->logger_file[0] = lctx->logger_file[1] = lctx->logger_file[2] = lctx->logger_file[3] = NULL;
	return 1;
}


C_CODE_END


